在 Angular 16 中,withComponentInput
可以將路由資料綁定到Input decorator
。相同的功能也適用於signal input
。
以下路由資訊可以綁定到Signal Input訊號輸入:
// route-data.routes.ts
import { Route } from '@angular/router';
import { getPerson } from './star-war.api';
export const routeDataRoutes: Route[] = [
{
path: '',
loadComponent: () => import('./home.component'),
},
{
path: 'route-path-param/:id',
loadComponent: () => import('./route-path-param.component'),
data: {
jedi: 'Luke Skywalker',
sith: 'Darth Maul'
},
resolve: {
vader: () => getPerson(4),
}
},
{
path: 'component-input-precedence/:name/p/:id',
loadComponent: () => import('./component-input-precedence.component'),
data: {
name: 'b',
},
resolve: {
name: () => Promise.resolve('c')
}
}
];
routeDataRoutes
延遲載入具有路由資料 (route data) 的組件。 route-path-param/:id
路徑載入 RoutePathParamComponent
組件,而 component-input-precedence/:name/p/:id
路徑載入 ComponentInputPrecedenceComponent 組件。
import { Route } from '@angular/router';
import { routeDataRoutes } from './route-data.routes';
export const routes: Route[] = [
{
path: 'home',
loadChildren: () => routeDataRoutes
},
{
path: '',
pathMatch: 'full',
redirectTo: '/home',
},
{
path: '**',
redirectTo: '/home'
}
]
routeDataRoutes
成為 /home
路徑的子路由。
import { provideRouter, withComponentInputBinding } from '@angular/router';
import { routes } from './app.routes';
export const appConfig = {
providers: [
provideRouter(routes, withComponentInputBinding()),
… other providers …
]
}
在provideRouter
函數中,第一個參數是路由,第二個參數是withComponentInputBinding
函數。
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { RouterOutlet, RouterLink } from '@angular/router';
@Component({
selector: 'app-home',
standalone: true,
imports: [RouterOutlet, RouterLink],
template: `
<nav>
<a [routerLink]="['route-path-param', '100']" [queryParams]="queryParams">Lazy-load Route Data</a>
<a [routerLink]="['component-input-precedence', 'a', 'p', '2']" [queryParams]="queryParams2">Component Input Precedence</a>
</nav>
<router-outlet />
`,
})
export default class HomeComponent {
queryParams = {
movie: 'Star War',
director: 'George Lucas'
};
queryParams2 = {
id: '1'
}
}
導覽列新增RouterLink
屬性,用於將參數 (Parameters) 和查詢參數 (Query Parameters) 綁定到路徑 (Route Path)。 該組件將 queryParams
和 param 100
綁定到route-path-param
路徑。它還將 queryParams2
和兩個參數 a
和 2
綁定到Component Input Precedence
路徑。
{
path: 'route-path-param/:id',
loadComponent: () => import('./route-path-param.component'),
data: {
jedi: 'Luke Skywalker',
sith: 'Darth Maul'
},
resolve: {
vader: () => getPerson(4),
}
},
export default class RoutePathParamComponent {
// path param
id = input();
// query parameters
movie = input<string>();
director = input<string>();
// route data
jedi = input<string>();
// route data
sith = input<string>();
// route resolver
vader = input<Person | undefined>();
}
id
參數映射到 id
signal input。 查詢參數 movie
和 director
被映射到 movie
和 director
signal inputs。路線資料 jedi
和 sith
被映射到 jedi
和 sith
signal inputs。 Resolver 呼叫 getPerson
函數並將結果儲存到 vader
signal input。
template: `
<app-component-input-container>
<h3>Signal Inputs from activated routes</h3>
<p>Path Param: {{ id() }}</p>
<p class="title">Query Params</p>
<div class="border">
<p>Movie: {{ movie() }}</p>
<p>Director: {{ director() }}</p>
</div>
<p class="title">Route Data</p>
<div class="border">
<p>Jedi: {{ jedi() }}</p>
<p>Sith: {{ sith() }}</p>
</div>
@let evil = vader();
@if (evil) {
<p class="title">Resolved Data</p>
<div class="border">
<p>Name: {{ evil.name }}</p>
<p>Height: {{ evil.height }}</p>
<p>Mass: {{ evil.mass }}</p>
</div>
}
</app-component-input-container>
根據withComponentInputBinding
的來源碼來看,資料 (route data) 優先權最高,參數 (parameter) 次之,查詢參數 (query parameter) 優先權最低。 如果路由資料和查詢參數具有相同的鍵,則 signal input 將與路由資料綁定。
{
path: 'component-input-precedence/:name/p/:id',
loadComponent: () => import('./component-input-precedence.component'),
data: {
name: 'b',
},
resolve: {
name: () => Promise.resolve('c')
}
}
queryParams2 = {
id: '1'
}
export default class ComponentInputPrecedenceComponent {
// path param
id = input();
// resolved data
name = input<string>();
activatedRoute = inject(ActivatedRoute);
queryParamsId = toSignal(this.activatedRoute.queryParamMap.pipe(
map((params) => params.get('id'))), { initialValue: '' });
paramsId = toSignal(this.activatedRoute.paramMap.pipe(
map((params) => params.get('id'))), { initialValue: '' });
paramsName = toSignal(this.activatedRoute.paramMap.pipe(
map((params) => params.get('name'))), { initialValue: '' });
dataName = toSignal(this.activatedRoute.data.pipe(
map((params) => params['name'])), { initialValue: ''});
}
在組件中,我注入ActivatedRoute
以從目前路由中提取查詢參數 (query parameter)、參數 (parameter) 和路由資料 (route data)。 queryParamsId
、paramsId
和 id
分別為 1、2 和 2。 dataName
和 name
分別是 a
和 c
。
<app-component-input-container>
<h3>Component Input Binding Precedence</h3>
<p>Route data precedence: data > param > query param</p>
<p>Query Param Id: {{ queryParamsId() }}, Param Id: {{ paramsId() }}, Input Id: {{ id() }}</p>
<p>Param Id: {{ paramsName() }}, Data: {{ dataName() }}, Input Name: {{ name() }}</p>
</app-component-input-container>
如果您不想啟用 withComponentInputBinding
功能,那麼您可以考慮安裝 ngxtension
函式庫並使用其函數來取得路由資訊 (route data) 作為 signal
。
injectParams
- 使開發人員能夠從目前路由注入參數作為 signal
injectQueryParams
- 使開發人員能夠從目前路由注入查詢參數作為 signal
injectRouteData
- 使開發人員能夠將目前路由的資料作為 signal
withComponentInputBinding
功能後,路由參數、查詢參數、資料和解析資料可以綁定到 Signal Input。withComponentInputBinding
功能,可以注入 ActivatedRoute
,從目前路由中提取值並使用 toSignal
建立 signal
。componentInputBinding
的優先權從高到低依序是路由資料、路由參數、路由查詢參數。ngxtension
函式庫 (library) 包含從目前路由 (current route) 注入路由資訊 (route data) 的實用函數 (utility functions)。當開發人員不想啟用 withComponentInputBinding
時,這是一種替代方案。鐵人賽第13天就這樣結束了。